/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package src;

import java.util.logging.Level;
import java.util.logging.Logger;

class SinThread extends Thread {

    private int start;
    private int end;
    private double sum = 0;

    SinThread(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    public void run() {        
        for (int k = start; k < end; k++) { 
            sum += Math.sin(k);
        }
    }

    double getSum() {
        return sum;
    }
}

/**
 *
 * @author Oksana_Moroz
 */
public class Pr1_1 {

    public static double calculateSin(int n, int numThreads) {
        SinThread[] ths = new SinThread[numThreads]; 
        int all = 2 * n + 1;
        int assignment = (all % numThreads == 0) ? (all / numThreads) 
                : (all / numThreads + 1);
        int given = -n;
        for (int i = 0; i < ths.length; i++) {
            int end = given + assignment;
            ths[i] = new SinThread(given, Math.min(end, n + 1));
            ths[i].start();
            given = end;
        }

        double sum = 0;
        for (int i = 0; i < ths.length; i++) {
            try {
                ths[i].join();
                sum += ths[i].getSum();
            } catch (InterruptedException ex) {
                Logger.getLogger(Pr1_1.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return sum;
    }

    public static void testOptimalNumThreads(int n) {
        long min = Long.MAX_VALUE;
        int numThreads = Integer.MAX_VALUE;
        for (int i = 1; i < 100; i++) {
            long start = System.currentTimeMillis();
            calculateSin(n, i);
            long end = System.currentTimeMillis();
            long diff = end - start;
            if (diff < min) {
                min = diff;
                numThreads = i;
            }
        }
        System.out.println("The most optimal numThreads = " + numThreads
                + ", time = " + min);
    }

    public static void main(String[] args) {
        System.out.println(calculateSin(10, 5));
        testOptimalNumThreads(10000);
    }
}